#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <gmp.h>

#define BIT_PRECISION 10000
#define ITERATIONS 10

int main(void)
{
	mpf_set_default_prec(BIT_PRECISION);

	mpf_t a0;
	mpf_t a1;
	mpf_t y0;
	mpf_t y1;
	mpf_t aux, aux2, aux3;
	unsigned long int power_of_two;

	mpf_init_set_ui(a0, 6);
	mpf_init(a1);
	mpf_init(y0);
	mpf_init(y1);
	mpf_init(aux);
	mpf_init(aux2);
	mpf_init(aux3);
	mpf_init_set_ui(aux2, 1);

	// Raiz(2)
	mpf_sqrt_ui(aux, 2);
	// aux = 4 * raiz(2)
	mpf_mul_ui(aux, aux, 4);
	// a0 = 6 - 4 * raiz(2)
	mpf_sub(a0, a0, aux);

	// Raiz(2)
	mpf_sqrt_ui(aux, 2);
	// y0 = raiz(2) - 1
	mpf_sub_ui(y0, aux, 1);

//	mpf_out_str(stdout, 10, BIT_PRECISION, y0);

	int i;
	for (i = 0; i < ITERATIONS; i++) {
		// Calculando y1:
		// Raiz(2)
		mpf_sqrt_ui(aux, 2);
		// y0 = y0 ^ 4
		mpf_pow_ui(y0, y0, 4);
		// aux = 1 - y0
		mpf_ui_sub(aux, 1, y0);
		//mpf_out_str(stdout, 10, BIT_PRECISION, aux);
		// aux = raiz(aux)
		mpf_sqrt(aux, aux);
		// aux = raiz(aux)
		mpf_sqrt(aux, aux);
		// aux2 = 1 - aux
		mpf_ui_sub(aux2, 1, aux);
		// aux3 = 1 + aux
		mpf_add_ui(aux3, aux, 1);
		// y1 = aux2 / aux3
		mpf_div(y1, aux2, aux3);
		putchar('\n');
		//printf("y1 = ");
		//mpf_out_str(stdout, 10, BIT_PRECISION, y1);
		putchar('\n');

		// Calculando a1:
		// aux = y1 ^ 2
		mpf_pow_ui(aux, y1, 2);
		// aux = aux + y1
		mpf_add(aux, aux, y1);
		// aux = aux +1
		mpf_add_ui(aux, aux, 1);

		// power_of_two = 2 * i + 3
		power_of_two = pow(2, (2 * i) + 3);
		// aux2 = y1 * power_of_two
		mpf_mul_ui(aux2, y1, power_of_two);

		// aux3 = aux * aux2
		mpf_mul(aux3, aux, aux2);
		//mpf_out_str(stdout, 10, BIT_PRECISION, aux3);

		// aux = y1 + 1
		mpf_add_ui(aux, y1, 1);
		// aux = aux ^ 4
		mpf_pow_ui(aux, aux, 4);
		// aux = aux * a0
		mpf_mul(aux, aux, a0);

		// a1 = aux - aux3
		mpf_sub(a1, aux, aux3);

		printf("y1 = ");
		mpf_out_str(stdout, 10, BIT_PRECISION, y1);
		printf("\na1 = ");
		mpf_out_str(stdout, 10, BIT_PRECISION, a1);

		mpf_ui_div(aux, 1, a1);
		printf("\nPI = ");
		mpf_out_str(stdout, 10, BIT_PRECISION, aux);

		mpf_set(y0, y1);
		mpf_set(a0, a1);
	}

	//putchar('\n');
	//mpf_out_str(stdout, 10, BIT_PRECISION, a1);
	putchar('\n');

	return EXIT_SUCCESS;
}
